<?php
/**
 * The dispatcher class.
 */
class Dispatcher {
    protected $router = null;
    /**
     * The request object.
     * @var Request
     */
	protected $request = null;
    /**
     * The response object.
     * @var Response
     */
	protected $response = null;
    /**
     * The page object.
     * @var Page
     */
	protected $page = null;
    /**
     * The renderer object.
     * @var View_Renderer
     */
    protected $renderer = null;

    /**
     * The constructor. It initialses the Request and Response objects.
     */
	public function __construct($router) {
	    $this->router = $router;
		$this->request = new Request();
		$this->response = new Response();
	}

    /**
     * Get the request object.
     * @return Request
     */
	public function getRequest() {
		return $this->request;
	}

    /**
     * Get the response object.
     * @return Response
     */
	public function getResponse() {
		return $this->response;
	}

    /**
     * Set the view renderer.
     * @param View_Renderer $renderer
     */
    public function setViewRenderer(View_Renderer $renderer) {
        $this->renderer = $renderer;
    }

    /**
     * Get the renderer.
     * @return View_Renderer
     */
    public function getViewRenderer() {
        return $this->renderer;
    }

    /**
     * Dispatch. Do the work.
     * @throws Dispatcher_Exception
     */
	public function dispatch() {
	    $route = $this->router->route($this->request->getRequestUri());
	    if($route === null) {
	        $route = new Route('', Framework::getConfig()->getSection('general')->page404, Framework::getConfig()->getSection('general')->method404);
	    }
	    $this->request->setRoute($route);
	    $pagename = $route->getClass();
	    $this->page = new $pagename($this->request, $this->response);
	    $this->page->getView()->setRenderer($this->renderer);
	    $methodname = $route->getMethod();
	    $methodlist = get_class_methods($this->page);
	    
        if(in_array('preDispatch', $methodlist)) {
            $this->page->preDispatch();
        }

        $this->response->sendHeaders();
		if(!in_array($methodname, $methodlist)) {
			throw new Dispatcher_Exception("Method '$methodname' does not exist.");
		}
        $this->page->$methodname();

        if($this->page->getView() instanceof View) {
            $this->page->getView()->render($this->page);
        }

        if(in_array('postDispatch', $methodlist)) {
            $this->page->postDispatch();
        }
    }
}
?>
